<?php

declare(strict_types=1);
/**
 * 船票API服务类
 * 统一管理调用同程接口的类库
 */

namespace app\common\service\third_party_api;

use think\Exception;
use app\common\service\Util;

class ShipApiService
{
    // API基础URL
    private $baseUrl;
    // 用户ID
    private $userId;
    // 密钥
    private $key;
    // Token
    private $token;

    /**
     * 构造函数
     * @param string $userId 用户ID，可选，默认从配置中获取
     * @param string $key 密钥，可选，默认从配置中获取
     */
    public function __construct($userId = null, $key = null)
    {
        // 从.env文件中读取配置
        $this->baseUrl = env('TC_URL', 'https://ebkapi.17u.cn');
        $this->userId = $userId ?: env('TC_USER_ID', '');
        $this->key = $key ?: env('TC_KEY', '');
        // 初始化时获取Token
        $this->token = $this->getToken();
    }

    /**
     * 获取Token
     * @return string
     * @throws Exception
     */
    public function getToken()
    {
        $url = $this->baseUrl . 'TCShipService/GetToken?userid=' . $this->userId;

        try {
            // 使用Util工具类的sendGetRequest方法发送请求
            $data = Util::sendGetRequest($url, ['userid' => $this->userId], ['Content-type' => 'application/x-www-form-urlencoded'], 15 * 60);

            if ($data['code'] !== '10001') {
                throw new Exception('获取Token失败: ' . $data['Msg']);
            }

            if (!isset($data['data']['SignToken']) || empty($data['data']['SignToken'])) {
                throw new Exception('Token获取失败: ' . json_encode($data));
            }

            return $data['data']['SignToken'];
        } catch (Exception $e) {
            throw new Exception('获取Token失败: ' . $e->getMessage());
        }
    }

    /**
     * 获取航线列表
     * @return array
     * @throws Exception
     */
    public function getShipLines()
    {
        // 重新获取Token（如果需要）
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        // 生成签名所需参数
        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        // 构建请求URL
        $url = $this->baseUrl . 'ShipLine/GetShipLines?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        // 准备POST数据
        $postData = ['userid' => $this->userId];

        // 发送请求
        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 创建订单
     * @param array $params 请求参数 ['ShipLineId' => string, 'OrderID' => string, 'VoyageId' => string, 'SeatId' => string, 'SeatName' => string, 'ShipSeatType' => string, 'Departure' => string, 'DeparturePort' => string, 'Destination' => string, 'ArrivePort' => string, 'DepartureTime' => string, 'ShipRunMinutes' => string, 'ContactName' => string, 'ContactNo' => string, 'ContactIdType' => string, 'ContactIdCard' => string, 'TicketAmount' => Decimal, 'TicketCount' => int, 'PassengersInfo' => List, 'VehicleInfo' => List, 'LockFirst' => Bool]
     * @return array
     * @throws Exception
     */
    public function createOrder($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'TCShipOrder/CreateOrder?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 检查订单是否可更改
     * @param array $params 请求参数 ['orderSerialId' => string]
     * @return array
     * @throws Exception
     */
    public function checkChangeAble($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'TCShipOrder/CheckChangeAble?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 查询改签航班接口
     * @param array $params 请求参数 ['orderSerialId' => string, 'date' => string]
     * @return array
     * @throws Exception
     */
    public function queryChangeVoyages($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'ShipVoyage/QueryChangeVoyages?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 订单改签
     * @param array $params 请求参数 ['orderSerialId' => string, 'tickets' => string, 'date' => string, 'shipName' => string, 'cabinId' => string, 'cabinName' => string, 'cardNos' => string]
     * @return array
     * @throws Exception
     */
    public function changeOrder($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'TCShipOrder/ChangeOrder?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 确认订单
     * @param array $params 请求参数 ['orderSerialId' => string]
     * @return array
     * @throws Exception
     */
    public function confirmOrder($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'TCShipOrder/ConfirmOrder?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 获取航班列表V2
     * @param array $params 请求参数 ['LineId' => string, 'SailDate' => string]
     * @return array
     * @throws Exception
     */
    public function getShipVoyagesV2($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'ShipVoyage/GetShipVoyagesV2?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 申请订单退款
     * @param array $params 请求参数 ['OrderNo' => string, 'RefOrderNo' => string, 'RefundType' => string, 'TicketList' => list]
     * @return array
     * @throws Exception
     */
    public function applyShipOrderRefund($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'ShipOrderRefund/ApplyShipOrderRefund?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 取消订单
     * @param array $params 请求参数 ['orderSerialId' => string]
     * @return array
     * @throws Exception
     */
    public function cancelOrder($params = [])
    {
        if (empty($this->token)) {
            $this->token = $this->getToken();
        }

        $timestamp = time() * 1000;
        $nonce = uniqid();
        $data = 'userid' . $this->userId;
        if (!empty($params)) {
            ksort($params);
            foreach ($params as $key => $value) {
                $data .= $key . $value;
            }
        }
        $signature = $this->generateSignature($timestamp, $nonce, $data);

        $url = $this->baseUrl . 'TCShipOrder/CancelOrder?timestamp=' . $timestamp . '&nonce=' . $nonce . '&signature=' . $signature;

        $postData = ['userid' => $this->userId];
        $postData = array_merge($postData, $params);

        $result = $this->sendPostRequest($url, $postData);

        return $result;
    }

    /**
     * 生成签名
     * @param int $timestamp 时间戳
     * @param string $nonce 随机字符串
     * @param string $data 数据
     * @return string
     */
    private function generateSignature($timestamp, $nonce, $data)
    {
        $signature_str = $signature = ($timestamp) . $nonce . $this->userId . $this->key . $this->token . $data;
        $arr = mb_str_split($signature_str);
        asort($arr);
        $signature_str_sort = implode('', $arr);
        $signature = md5($signature_str_sort);
        $signature = strtoupper($signature);

        return $signature;
    }

    /**
     * 发送POST请求
     * @param string $url 请求URL
     * @param array $postData POST数据
     * @return array
     * @throws Exception
     */
    private function sendPostRequest($url, $postData)
    {
        // 调用Util工具类中的静态方法发送POST请求
        try {
            return Util::sendPostRequest($url, $postData);
        } catch (Exception $e) {
            throw new Exception('请求失败: ' . $e->getMessage());
        }
    }
}
